package com.library.service;

import com.library.dto.*;
import com.library.entity.User;
import com.library.exception.BusinessException;
import com.library.exception.NotFoundException;
import com.library.repository.BorrowRecordRepository;
import com.library.repository.FavoriteRepository;
import com.library.repository.NotificationRepository;
import com.library.repository.ReservationRepository;
import com.library.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户服务类
 * 负责处理用户相关的业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final BorrowRecordRepository borrowRecordRepository;
    private final FavoriteRepository favoriteRepository;
    private final ReservationRepository reservationRepository;
    private final NotificationRepository notificationRepository;

    /**
     * 获取用户个人信息
     */
    public UserDTO getUserProfile(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException("用户不存在"));
        return convertToDTO(user);
    }

    /**
     * 更新用户个人信息
     */
    @Transactional
    public UserDTO updateUserProfile(Long userId, UserProfileDTO dto) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException("用户不存在"));

        if (dto.getEmail() != null) {
            user.setEmail(dto.getEmail().trim());
        }
        if (dto.getPhone() != null) {
            user.setPhone(dto.getPhone().trim());
        }

        user = userRepository.save(user);
        log.info("更新用户个人信息成功: {} (ID: {})", user.getUsername(), user.getId());
        return convertToDTO(user);
    }

    /**
     * 修改密码
     */
    @Transactional
    public void changePassword(Long userId, PasswordChangeDTO dto) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException("用户不存在"));

        // 验证旧密码
        if (!passwordEncoder.matches(dto.getOldPassword(), user.getPassword())) {
            throw new BusinessException("旧密码错误");
        }

        // 设置新密码
        user.setPassword(passwordEncoder.encode(dto.getNewPassword()));
        userRepository.save(user);
        log.info("修改密码成功: {} (ID: {})", user.getUsername(), user.getId());
    }

    /**
     * 获取用户列表（管理员）
     */
    public PageResponse<UserDTO> getUserList(String keyword, String role, String status, 
                                             Integer page, Integer size, String sort, String order) {
        // 搜索用户
        List<User> users;
        if (keyword != null && !keyword.trim().isEmpty() || 
            (role != null && !role.trim().isEmpty()) || 
            (status != null && !status.trim().isEmpty())) {
            users = userRepository.searchUsers(keyword, role, status);
        } else {
            users = userRepository.findAll();
        }
        
        // 手动排序
        String sortField = sort != null ? sort : "createdAt";
        boolean isDesc = "desc".equalsIgnoreCase(order);
        users.sort((a, b) -> {
            int result = 0;
            switch (sortField) {
                case "username":
                    result = a.getUsername().compareTo(b.getUsername());
                    break;
                case "role":
                    result = (a.getRole() != null ? a.getRole() : "").compareTo(b.getRole() != null ? b.getRole() : "");
                    break;
                case "status":
                    result = (a.getStatus() != null ? a.getStatus() : "").compareTo(b.getStatus() != null ? b.getStatus() : "");
                    break;
                case "createdAt":
                default:
                    if (a.getCreatedAt() != null && b.getCreatedAt() != null) {
                        result = a.getCreatedAt().compareTo(b.getCreatedAt());
                    }
                    break;
            }
            return isDesc ? -result : result;
        });

        // 手动分页
        int start = (page - 1) * size;
        int end = Math.min(start + size, users.size());
        List<User> pagedUsers = users.subList(Math.max(0, start), end);

        // 转换为DTO
        List<UserDTO> content = pagedUsers.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        // 计算总页数
        int totalPages = (int) Math.ceil((double) users.size() / size);

        return new PageResponse<>(content, (long) users.size(), page, size, totalPages);
    }

    /**
     * 获取用户详情（管理员）
     */
    public UserDTO getUserById(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new NotFoundException("用户不存在"));
        return convertToDTO(user);
    }

    /**
     * 修改用户角色（管理员）
     */
    @Transactional
    public void updateUserRole(Long id, String role, Long currentUserId) {
        // 不能修改自己的角色
        if (id.equals(currentUserId)) {
            throw new BusinessException("不能修改自己的角色");
        }

        User user = userRepository.findById(id)
                .orElseThrow(() -> new NotFoundException("用户不存在"));

        // 验证角色
        if (!"user".equals(role) && !"admin".equals(role)) {
            throw new BusinessException("无效的角色");
        }

        user.setRole(role);
        userRepository.save(user);
        log.info("修改用户角色成功: {} (ID: {}) -> {}", user.getUsername(), user.getId(), role);
    }

    /**
     * 修改用户状态（管理员）
     */
    @Transactional
    public void updateUserStatus(Long id, String status, Long currentUserId) {
        // 不能禁用自己
        if (id.equals(currentUserId) && "inactive".equals(status)) {
            throw new BusinessException("不能禁用自己");
        }

        User user = userRepository.findById(id)
                .orElseThrow(() -> new NotFoundException("用户不存在"));

        // 验证状态
        if (!"active".equals(status) && !"inactive".equals(status)) {
            throw new BusinessException("无效的状态");
        }

        user.setStatus(status);
        userRepository.save(user);
        log.info("修改用户状态成功: {} (ID: {}) -> {}", user.getUsername(), user.getId(), status);
    }

    /**
     * 用户主动注销账号
     */
    @Transactional
    public void deleteUserAccount(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException("用户不存在"));

        // 检查是否存在未归还的图书
        if (borrowRecordRepository.existsByUserIdAndStatusIn(userId, List.of("borrowed", "pending_return"))) {
            throw new BusinessException("注销失败，存在未归还的图书");
        }

        // 删除关联数据
        favoriteRepository.deleteByUserId(userId);
        reservationRepository.deleteByUserId(userId);
        notificationRepository.deleteByUserId(userId);
        borrowRecordRepository.deleteByUserId(userId);

        userRepository.delete(user);
        log.info("用户已注销并删除所有关联数据: {} (ID: {})", user.getUsername(), user.getId());
    }

    /**
     * 将User实体转换为UserDTO
     */
    private UserDTO convertToDTO(User user) {
        return new UserDTO(
                user.getId(),
                user.getUsername(),
                user.getRole(),
                user.getEmail(),
                user.getPhone(),
                user.getStatus(),
                user.getCreatedAt()
        );
    }
}

